package com.cmict.data.form.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cmict.data.form.api.entity.BpmForm;
import com.cmict.data.form.api.entity.SysCategory;
import com.cmict.data.form.api.entity.dataobject.SysFormDO;
import com.cmict.data.form.api.entity.dataobject.SysFormItemRespVO;
import com.cmict.data.form.api.entity.vo.SysFormReqVO;
import com.cmict.data.form.api.mapper.SysFormMapper;
import com.cmict.data.form.api.service.SysCategoryService;
import com.cmict.data.form.api.service.SysCurrencyService;
import com.cmict.data.form.api.service.SysFormService;
import com.cmict.data.framework.common.exception.ServiceException;
import com.cmict.data.framework.common.pojo.CommonResult;
import com.cmict.data.framework.common.pojo.PageResult;
import com.cmict.data.framework.common.util.collection.CollectionUtils;
import com.cmict.data.system.api.sql.SqlParameterCheck;
import com.cmict.data.framework.tenant.core.aop.TenantIgnore;
import com.cmict.data.system.api.permission.MenuApi;
import com.cmict.data.system.api.permission.dto.MenuDTO;
import com.cmict.data.system.api.user.AdminUserApi;
import com.cmict.data.system.api.user.dto.AdminUserRespDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.cmict.data.framework.common.pojo.CommonResult.error;
import static com.cmict.data.framework.common.pojo.CommonResult.success;
import static com.cmict.data.framework.common.util.collection.CollectionUtils.convertList;

@Service("sysFormService")
@RequiredArgsConstructor
@Slf4j
public class SysFormServiceImpl implements SysFormService {

    @Autowired
    private SysFormMapper sysFormMapper;

    @Resource
    private MenuApi menuApi;

    @Resource
    private SysCategoryService sysCategoryService;

    @Resource
    private SysCurrencyService sysCurrencyService;

    @Resource
    private AdminUserApi adminUserApi;

    @Value("${spring.datasource.dynamic.datasource.slave.name}")
    private String tableSchema;

    @Override
    public Boolean deleteSysForm(Long id) {
        SqlParameterCheck.checkDigitalMatch(String.valueOf(id));
        SysFormDO sysFormDO = sysFormMapper.selectById(id);
        if(null != sysFormDO && null != sysFormDO.getIsReference() && sysFormDO.getIsReference() != 0 ){
            return Boolean.FALSE;
        }
        sysFormMapper.deleteById(id);
        return Boolean.TRUE;
    }
    @Override
    public Boolean deleteSysFormChild(String tableName) {
        sysFormMapper.deleteFormOfTableName(tableName);
        /*if(ObjectUtil.isNotEmpty(sysFormDO)){
            sysFormMapper.deleteById(sysFormDO.getId());
        }*/
        return Boolean.TRUE;
    }



    @Override
    public String batchDeleteSysForm(Collection<Long> ids) {
        List<SysFormDO> list = sysFormMapper.selectBatchIds(ids);
        AtomicReference<Integer> countFalse = new AtomicReference<>(0);
        AtomicReference<Integer> countSuccess = new AtomicReference<>(0);
        list.forEach( sysFormDO -> {
            if(sysFormDO.getIsReference() != 0 ){
                countFalse.getAndSet(countFalse.get() + 1);
            }else{
                sysFormMapper.deleteById(sysFormDO.getId());
                countSuccess.getAndSet(countSuccess.get() + 1);
            }
        });
        if(countFalse.get() == ids.size()){
            return "所选数据删除失败！";
        }else if(countSuccess.get() == ids.size()){
            return "删除成功！";
        }else{
            return countSuccess.get() + "条删除成功，" + countFalse.get() + "条删除失败！" ;
        }
    }

    @Override
    public Boolean enable(Long id) {
        return sysFormMapper.enable(id);
    }

    @Override
    public Boolean disable(Long id) {
        return sysFormMapper.disable(id);
    }

    @Override
    public Boolean noRelease(Long id) {
        SqlParameterCheck.checkDigitalMatch(String.valueOf(id));
        SysFormDO sysForm = sysFormMapper.selectById(id);
        if(ObjectUtil.isNotEmpty(sysForm.getUseMenuId())){
            menuApi.deleteMenuForm(sysForm.getUseMenuId());
        }
        if(ObjectUtil.isNotEmpty(sysForm.getManageMenuId())){
            menuApi.deleteMenuForm(sysForm.getManageMenuId());
        }
        return sysFormMapper.noRelease(id);
    }

    @Override
    public String noReleaseBatch(Collection<Long> ids) {
        List<SysFormDO> list = sysFormMapper.selectBatchIds(ids);
        AtomicReference<Integer> countFalse = new AtomicReference<>(0);
        AtomicReference<Integer> countSuccess = new AtomicReference<>(0);
        list.forEach( sysFormDO -> {
            try{
                menuApi.deleteMenuForm(sysFormDO.getUseMenuId());
                menuApi.deleteMenuForm(sysFormDO.getManageMenuId());
            }catch(ServiceException e){
                log.error("菜单ID为"+sysFormDO.getUseMenuId()+"和"+sysFormDO.getManageMenuId()+"不存在");
            }
            if(sysFormDO.getIsReference() != 1 ){
                countFalse.getAndSet(countFalse.get() + 1);
            }else{
                sysFormMapper.noRelease(sysFormDO.getId());
                countSuccess.getAndSet(countSuccess.get() + 1);
            }
        });
        if(countFalse.get() == ids.size()){
            return "所选数据删除失败！";
        }else if(countSuccess.get() == ids.size()){
            return "删除成功！";
        }else{
            return countSuccess.get() + "条删除成功，" + countFalse.get() + "条删除失败！" ;
        }
    }

    @Override
    //@DataPermission(enable=false)
    public PageResult<SysFormItemRespVO> getFormPage(SysFormReqVO reqVO) {
        PageResult<SysFormDO> pageResult = sysFormMapper.selectPage(reqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return new PageResult<>(pageResult.getTotal()); // 返回空
        }
        // 获得拼接需要的数据
        Collection<Long> categoryIds = convertList(pageResult.getList(), SysFormDO::getCategoryId);
        Map<Long, SysCategory> categoryMap = sysCategoryService.getSysCategoryMap(categoryIds);
        // 拼接结果返回
        List<SysFormItemRespVO> formList = new ArrayList<>(pageResult.getList().size());
        pageResult.getList().forEach( form -> {
            SysFormItemRespVO sysFormItemRespVO = new SysFormItemRespVO();
            BeanUtils.copyProperties(form,sysFormItemRespVO);
            sysFormItemRespVO.setSysCategory(categoryMap.get(form.getCategoryId()));
            AdminUserRespDTO user = adminUserApi.getUser(Long.valueOf(form.getCreator())).getCheckedData();
            if(null != user){
                sysFormItemRespVO.setCreatorName(user.getUsername());
                formList.add(sysFormItemRespVO);
            }
        });
        return new PageResult<>(formList, pageResult.getTotal());
    }

    @TenantIgnore
    @Override
    public SysFormDO getSysForm(Long id) {
        return sysFormMapper.selectById(id);
    }

    @Override
    public Long createForm(SysFormDO formDO) {
        sysFormMapper.insert(formDO);
        return formDO.getId();
    }

    @Override
    public void updateForm(SysFormDO formDO) {
        SqlParameterCheck.checkDigitalMatch(String.valueOf(formDO.getId()));
        formDO.setReleaseTime(LocalDateTime.now());
        sysFormMapper.updateById(formDO);
    }

    @Override
    public SysFormDO selectOne(String formName) {
        return sysFormMapper.selectOne(formName);
    }

    @Override
    @TenantIgnore
    public SysFormDO selectOneByTableName(String tableName) {
        return sysFormMapper.selectOneByTableName(tableName);
    }

    @Override
    //@DataPermission(enable=false)
    public PageResult<SysFormItemRespVO> getFormPageRelease(SysFormReqVO reqVO) {
        PageResult<SysFormDO> pageResult = sysFormMapper.selectPageRelease(reqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return new PageResult<>(pageResult.getTotal()); // 返回空
        }
        // 获得拼接需要的数据
        Collection<Long> categoryIds = convertList(pageResult.getList(), SysFormDO::getCategoryId);
        Map<Long, SysCategory> categoryMap = sysCategoryService.getSysCategoryMap(categoryIds);
        List<MenuDTO> menuList = menuApi.getMenus().getCheckedData();
        Map<Long, MenuDTO> menuMap = menuList.stream().collect(Collectors.toMap(MenuDTO::getId, Function.identity(), (v1, v2)->v1));
        // 拼接结果返回
        List<SysFormItemRespVO> formList = new ArrayList<>(pageResult.getList().size());
        pageResult.getList().forEach( form -> {
            SysFormItemRespVO sysFormItemRespVO = new SysFormItemRespVO();
            BeanUtils.copyProperties(form,sysFormItemRespVO);
            sysFormItemRespVO.setSysCategory(categoryMap.get(form.getCategoryId()));
            sysFormItemRespVO.setUseMenu(menuMap.get(form.getUseMenuId()));
            sysFormItemRespVO.setManageMenu(menuMap.get(form.getManageMenuId()));
            AdminUserRespDTO user = adminUserApi.getUser(Long.valueOf(form.getCreator())).getCheckedData();
            if(null != user){
                sysFormItemRespVO.setCreatorName(user.getUsername());
                formList.add(sysFormItemRespVO);
            }
        });
        return new PageResult<>(formList, pageResult.getTotal());
    }

    @Override
    //@DataPermission(enable=false)
    public PageResult<SysFormItemRespVO> getFormPageNoRelease(SysFormReqVO reqVO) {
        PageResult<SysFormDO> pageResult = sysFormMapper.selectPageNoRelease(reqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return new PageResult<>(pageResult.getTotal()); // 返回空
        }
        // 获得拼接需要的数据
        Collection<Long> categoryIds = convertList(pageResult.getList(), SysFormDO::getCategoryId);
        Map<Long, SysCategory> categoryMap = sysCategoryService.getSysCategoryMap(categoryIds);
        // 拼接结果返回
        List<SysFormItemRespVO> formList = new ArrayList<>(pageResult.getList().size());
        pageResult.getList().forEach( form -> {
            SysFormItemRespVO sysFormItemRespVO = new SysFormItemRespVO();
            BeanUtils.copyProperties(form,sysFormItemRespVO);
            sysFormItemRespVO.setSysCategory(categoryMap.get(form.getCategoryId()));
            AdminUserRespDTO user = adminUserApi.getUser(Long.valueOf(form.getCreator())).getCheckedData();
            if(null != user){
                sysFormItemRespVO.setCreatorName(user.getUsername());
                formList.add(sysFormItemRespVO);
            }
        });
        return new PageResult<>(formList, pageResult.getTotal());
    }

    @Override
    public Map<Long, SysFormDO> getFormMap(Set<Long> formIds) {
        if (CollUtil.isEmpty(formIds)) {
            return Collections.emptyMap();
        }
        return CollectionUtils.convertMap(this.getFormList(formIds), SysFormDO::getId);
    }

    @Override
    public List<SysFormDO> getFormList(Collection<Long> ids) {
        return sysFormMapper.selectBatchIds(ids);
    }

    @Override
    public List<SysFormDO> selectListRelease() {
        return sysFormMapper.selectListRelease();
    }

    @Override
    public List<SysFormDO> selectListReleaseByEncode(String tableName) {
        return sysFormMapper.selectListReleaseByEncode(tableName);
    }
    @Override
    public List<SysFormDO> selectListAll() {
        return sysFormMapper.selectListAll();
    }

    @Override
    public Long getFormIdByTableName(String tableName) {
        SysFormDO sysFormDO = sysFormMapper.selectOne("table_name",tableName);
        return sysFormDO.getId();
    }

    @Override
    public Set<Long> getUserMenuId() {
        return sysFormMapper.getUserMenuId();
    }

    @Override
    public List<SysFormDO> getSysFormByUseMenuIds(String menuIds) {
        return sysFormMapper.getSysFormByUseMenuIds(menuIds);
    }

    @Override
    public List<SysFormDO> getChildSysFormByIds(Long parentId) {
        return sysFormMapper.getChildSysFormByIds(parentId);
    }

    @Override
    public Set<SysFormDO> getSysFormByFormMenuIds(String menuIds) {
        return sysFormMapper.getSysFormByFormMenuIds(menuIds);
    }

    @Override
    public Set<Long> getManageMenuId() {
        return sysFormMapper.getManageMenuId();
    }

    @Override
    public List<SysFormDO> selectListReleaseManage() {
        return sysFormMapper.selectListReleaseManage();
    }


    @Override
    //@DataPermission(enable=false)
    public PageResult<SysFormItemRespVO> getSysFormPageIsenable(SysFormReqVO reqVO) {
        PageResult<SysFormDO> pageResult = sysFormMapper.getSysFormPageIsenable(reqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return new PageResult<>(pageResult.getTotal()); // 返回空
        }
        // 获得拼接需要的数据
        Collection<Long> categoryIds = convertList(pageResult.getList(), SysFormDO::getCategoryId);
        Map<Long, SysCategory> categoryMap = sysCategoryService.getSysCategoryMap(categoryIds);
        // 拼接结果返回
        List<SysFormItemRespVO> formList = new ArrayList<>(pageResult.getList().size());
        pageResult.getList().forEach( form -> {
            SysFormItemRespVO sysFormItemRespVO = new SysFormItemRespVO();
            BeanUtils.copyProperties(form,sysFormItemRespVO);
            sysFormItemRespVO.setSysCategory(categoryMap.get(form.getCategoryId()));
            AdminUserRespDTO user = adminUserApi.getUser(Long.valueOf(form.getCreator())).getCheckedData();
            if(null != user){
                sysFormItemRespVO.setCreatorName(user.getUsername());
                List<SysFormDO> sysFormDOList =  getChildSysFormByIds(sysFormItemRespVO.getId());
                JSONArray json = new JSONArray();
                if(ObjectUtil.isNotEmpty(sysFormDOList)){
                    for (int j = 0; j <sysFormDOList.size() ; j++) {
                        json.add(sysFormDOList.get(j));
                    }
                }
                sysFormItemRespVO.setChildFormJsonData(json.toString());
                formList.add(sysFormItemRespVO);
            }
        });
        return new PageResult<>(formList, pageResult.getTotal());
    }


    @Override
    public BpmForm getFormConfig(Long formId) {
        BpmForm bpmForm = new BpmForm();
        SysFormDO sysFormDO = sysFormMapper.selectById(formId);
        bpmForm.setId(sysFormDO.getId());
        bpmForm.setName(sysFormDO.getFormName());
        JSONObject conf = JSONObject.parseObject(sysFormDO.getFormJsonUser());
        String fields= conf.getJSONArray("fields").toString();
        //再将String转为List<String>
        List<String> list = JSONObject.parseArray(fields,String.class);
        bpmForm.setFields(list);

        bpmForm.setConf(conf.fluentRemove("fields").toJSONString());
        return bpmForm;
    }
    @Override
    public SysFormDO selectById(Long formId) {
        SysFormDO sysFormDO = sysFormMapper.selectById(formId);
        return sysFormDO;
    }

    @Override
    public List<Map<String, Object>> getFieldNameList(String tableName) {
        String sql = "SELECT  column_name  as columnName,column_type  as columnType,column_comment  as comment, CONCAT(column_name , '_' ,column_comment) as columnComment FROM INFORMATION_SCHEMA.COLUMNS  WHERE   table_schema= '" + tableSchema + "' AND   table_name ='"+tableName+"';";

        return sysFormMapper.getTableNameList(sql);

    }

    @Override
    public CommonResult getByFormMenu(String tableName) {
        SysFormDO sysFormDO = sysFormMapper.selectOneByTableName(tableName);
        if(ObjectUtil.isNotEmpty(sysFormDO)){
            CommonResult<MenuDTO> menuDTO = menuApi.getFromId(sysFormDO.getId());
            return success(menuDTO);
        }
        return error(500,"无法获取表单");
    }
}
